<template>
  <div class="app-container">
    <div class="header">
      <el-button 
        type="primary" 
        size="mini" 
        @click="handleAddEnvSpectrum"
        :disabled="baseInfo.constructStateName === '已完成'"
        >新增环境光谱</el-button
      >
      <el-button 
        type="primary" 
        size="mini" 
        @click="handleAddDetail"
        :disabled="baseInfo.constructStateName === '已完成'"
        >新增明细
        <el-tooltip
          class="item"
          effect="dark"
          content="通过csv文件导入,最后一列为标准值。波长范围必须与已有明细数据保持一致。"
          placement="top"
        >
          <i class="el-icon-question"></i>
        </el-tooltip>
      </el-button>
      <el-button 
        type="primary" 
        size="mini" 
        @click="resetDetail"
        :disabled="baseInfo.constructStateName === '已完成'"
        >重置明细</el-button
      >
      <el-button
        :disabled="tableData.length === 0 || baseInfo.constructStateName === '已完成'"
        type="primary"
        size="mini"
        @click="deleteDetail"
        >删除明细</el-button
      >
      <el-button 
        type="primary" 
        size="mini" 
        @click="handleDownload"
        :disabled="baseInfo.constructStateName === '已完成'"
        >生成示例文件</el-button
      >

      <el-button 
        type="primary" 
        size="mini" 
        @click="handleIssue"
        :disabled="baseInfo.constructStateName === '已完成'"
        >提交</el-button
      >

      <!-- <el-button type="primary" plain size="small" @click="handleAdd"
        >删除明细</el-button
      >

      <el-button type="primary" plain size="mini" @click="handleViewHistory"
        >关闭</el-button
      > -->
    </div>
    <!-- 基本信息 -->
    <el-card class="base-box-card">
      <div slot="header" class="card-header">基本信息</div>
      <el-row :gutter="2">
        <el-col :span="4">建模数据编号：{{ baseInfo.constructNo }}</el-col>
        <el-col :span="3"
          >建模数据状态：{{ baseInfo.constructStateName }}
        </el-col>
        <el-col :span="2">成分：{{ baseInfo.constituentName }}</el-col>
        <el-col :span="2">部门：{{ baseInfo.departmentName }}</el-col>
        <el-col :span="4">仪器编号：{{ baseInfo.instrumentNo }}</el-col>
        <el-col :span="3">仪器名称：{{ baseInfo.instrumentName }}</el-col>
        <el-col :span="3">数据构建人：{{ baseInfo.creator }}</el-col>
        <el-col :span="3">采样时间：{{ baseInfo.samplingTime }}</el-col>
      </el-row>
    </el-card>

    <div class="main-row">
      <el-col class="left-size">
        <el-card class="env-box-card" shadow="never">
          <!-- 环境光谱数据 -->
          <div slot="header" class="card-header">环境光谱</div>
          <el-table
            :data="[envSpectrum]"
            style="width: 100%"
          >
            <el-table-column prop="envSpectrumNo" label="环境光谱编号" align="center" width="180" />
            <el-table-column prop="departmentName" label="生产车间" align="center" />
            <el-table-column prop="instrumentNo" label="仪器编号" align="center"  width="180" />
            <el-table-column prop="instrumentName" label="仪器名称" align="center" />
            <el-table-column prop="samplingTime" label="采样时间" align="center" width="180" />
            <el-table-column
              label="操作"
              align="center"
              class-name="small-padding fixed-width"
              v-if="Object.keys(envSpectrum).length > 0"
            >
              <template #default>
                <el-button 
                  type="text" 
                  size="small" 
                  @click="deleteEnvSpectrum"
                  :disabled="baseInfo.constructStateName === '已完成'"
                  >删除</el-button
                >
                <!-- <el-button type="text" size="small">波长</el-button> -->
              </template>
            </el-table-column>
          </el-table>
        </el-card>
        <el-card class="box-card" shadow="never">
          <div slot="header" class="card-header">明细列表</div>
          <!-- 建模数据明细列表 -->
          <el-table
            ref="dataTable"
            :data="tableData"
            height="calc(40vh)"
            style="width: 100%; height: 100%; overflow-y: auto"
            @selection-change="handleSelectionChange"
          >
            <el-table-column type="selection" width="55" align="center" />
            <el-table-column
              prop="constructDetailNo"
              label="建模数据详细编号"
              width="160px"
              align="center"
            />
            <el-table-column prop="standard" label="标准值" align="center" />
            <el-table-column prop="constructdTypeName" label="数据划分" align="center">
              <template #default="scope">
                <el-tag :type="dataTypeTag(scope.row.constructdTypeName)">
                  {{ scope.row.constructdTypeName }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="constructdStateName" label="状态" align="center">
              <template #default="scope">
                <el-tag
                  :type="
                    scope.row.constructdStateName === '剔除'
                      ? 'danger'
                      : 'success'
                  "
                >
                  {{ scope.row.constructdStateName }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
              <template #default="scope" v-if="tableData.length > 0">
                <el-button
                  type="text"
                  size="small"
                  @click="deleteDetailById(scope.row.constructDetailId)"
                  :disabled="baseInfo.constructStateName === '已完成'"
                  >删除</el-button
                >
                <!-- <el-button type="text" size="small">吸光度</el-button> -->
              </template>
            </el-table-column>
          </el-table>
          <pagination
            v-show="total > 0"
            :total="total"
            :page.sync="queryParams.pageNum"
            :limit.sync="queryParams.pageSize"
            @pagination="getList"
          />
        </el-card>
      </el-col>
      <el-col class="right-size">
        <el-card shadow="never">
          <el-form  label-width="100px">
            <el-form-item label="异常剔除方法">
              <el-select
                v-model="selectForm.outlierMethod"
                placeholder="请选择"
                style="width: 100%;"
                :disabled="baseInfo.constructStateCode === '02'"
              >
                <el-option label="不剔除" value="no_detect" />
                <el-option label="PCA结合马氏距离" value="pca_mahalanobis" />
              </el-select>
            </el-form-item>

            <el-form-item label="数据划分方法">
              <el-select v-model="selectForm.splitMethod" placeholder="请选择" style="width: 100%;" :disabled="baseInfo.constructStateCode === '02'">
                <!-- 示例选项，可根据实际需求补充 -->
                <el-option
                  label="Kennard-Stone(KS)算法"
                  value="kennard_stone"
                />
                <el-option
                  label="光谱-理化值共生距离算法（SPXY）"
                  value="spxy"
                />
              </el-select>
            </el-form-item>

            <el-form-item label="验证集占比">
              <el-input
                v-model.number="selectForm.cvRatio"
                placeholder="请输入0-1之间的小数"
                type="number"
                :min="0"
                :max="1"
                step="0.01"
                style="width: 100%;"
                @change="handleCvRatioChange"
                :disabled="baseInfo.constructStateCode === '02'"
              />
            </el-form-item>

            <el-form-item label="内置环境光谱">
              <el-select
                v-model="selectForm.useEnvSpectrum"
                placeholder="请选择"
                style="width: 100%;"
                :disabled="baseInfo.constructStateCode === '02'"
              >
                <el-option label="否" value="no" />
                <el-option label="是" value="yes" />
              </el-select>
            </el-form-item>

            <el-form-item style="text-align: right; margin-bottom: 10px;">
              <el-button 
                type="primary" 
                @click="handleAbnormalPartition"
                :disabled="baseInfo.constructStateCode === '02'"
                >处理</el-button
              >
              <el-button :disabled="baseInfo.constructStateCode === '02'">重置</el-button>
            </el-form-item>
          </el-form>
        </el-card>
        <el-tabs v-model="activeTab" style="height: 90%">
          <!-- 第一个 Tab：吸光度曲线图 -->
          <el-tab-pane label="吸光度曲线" name="chart" style="height: 100%">
            <stacked-line-chart :seriesData="series" :xAxisData="xAxis" />
          </el-tab-pane>

          <!-- 第二个 Tab：其他内容（如说明或表格） -->
          <el-tab-pane label="异常剔除散点图" name="info" style="height: 100%">
            <div style="width: 100%; height: 100%">
              <ScoreScatter
                v-if="activeTab === 'info'"
                :pc1="pc1"
                :pc2="pc2"
                :category="category"
              />
            </div>
          </el-tab-pane>
        </el-tabs>
      </el-col>
    </div>

    <el-dialog
      title="环境光谱明细"
      :visible.sync="envdialogVisible"
      width="80%"
      style="overflow: auto"
      append-to-body
    >
      <div class="env-dialog-body">
        <env-spectrum-detail
          ref="envSpectrumDetail"
          :is-row-visible="false"
          @selection-change="handleRowSelection"
        />
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm">确 定</el-button>
        <el-button @click="envdialogVisible = false">取 消</el-button>
      </div>
    </el-dialog>

    <!-- 弹窗 -->
    <el-dialog
      title="上传 CSV 文件"
      :visible.sync="uploadDeatil_dialogVisible"
      width="50%"
    >
      <div style="display: flex; justify-content: center">
        <el-upload
          ref="upload"
          class="upload-demo"
          drag
          action=""
          :auto-upload="false"
          :on-change="handleCSVUpload"
          accept=".csv"
        >
          <i class="el-icon-upload"></i>
          <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
          <div class="el-upload__tip" slot="tip">只能上传csv文件</div>
        </el-upload>
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="saveDetail" :disabled="!fileContent"
          >保 存</el-button
        >
        <el-button @click="handleCancelUpload">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import EnvSpectrumDetail from "@/views/spectrum/env_spectrum/index.vue";
import { updateConstruct, getConstruct } from "@/api/model/construct";
import {
  addConstructDetail,
  listConstructDetail,
  resetConstructDetail,
  submitAbnormalPartitionResult,
  delConstructDetailByConstrudtId,
  delConstructDetail,
} from "@/api/model/constructDetail";
import StackedLineChart from "@/views/tool/build/ChartComponent.vue";
import axios from "axios";
import ScoreScatter from "@/views/tool/build/ScoreScatter.vue";
import { listEnv_spectrum } from "@/api/spectrum/env_spectrum";
import { get } from "sortablejs";

export default {
  components: {
    EnvSpectrumDetail,
    StackedLineChart,
    ScoreScatter,
  },
  data() {
    return {
      activeTab: "chart", // 默认激活的 tab
      selectForm: {
        outlierMethod: "pca_mahalanobis",
        cvRatio: "0.2",
        splitMethod: "spxy",
        useEnvSpectrum: "no",
      },
      fileContent: null,
      selectedEnvSpectrum: null,
      tables: [],
      uploadDeatil_dialogVisible: false,
      envdialogVisible: false,
      baseInfo: {
        constructId: null,
        constructNo: "",
        constructStateName: "",
        constituentName: "",
        departmentName: "",
        instrumentNo: "",
        instrumentName: "",
        creator: "",
        sampleTime: "",
      },
      envSpectrum: {},
      tableData: [],
      selectedRows: [],
      series: [],
      xAxis: [],
      total: 0,
      queryParams: {
        pageNum: 1,
        pageSize: 10,
      },
      category: [],
      pc1: [],
      pc2: [],
      tempPartitionResults: new Map(), // 临时存储异常剔除结果，提交时才写入数据库
    };
  },
  mounted() {
    this.baseInfo = JSON.parse(this.$route.query.baseInfo || "{}");
    getConstruct(this.baseInfo.constructId).then((res) => {
      this.baseInfo = res.data;
      
      // 回显异常剔除方法和数据划分方法
      if (this.baseInfo.abnormalEliminationName) {
        this.selectForm.outlierMethod = this.baseInfo.abnormalEliminationName;
      }
      if (this.baseInfo.dataPartitioningName) {
        this.selectForm.splitMethod = this.baseInfo.dataPartitioningName;
      }
      if (this.baseInfo.testSize) {
        this.selectForm.cvRatio = this.baseInfo.testSize.toString();
      }
      
      if (this.baseInfo.sampleCategoryArray) {
        this.category = JSON.parse(this.baseInfo.sampleCategoryArray || "[]");
        this.pc1 = JSON.parse(res.data.pc1Array || "[]");
        this.pc2 = JSON.parse(res.data.pc2Array || "[]");
        console.log("查看建模数据的分类", this.category);
        this.activeTab = "info"; // 如果有分类数据，默认切换到 info tab
      }
      console.log("查看建模数据的基本信息", this.baseInfo);
    });
    // 通过id获取建模数据的基本信息
    if (this.baseInfo.envSpectrumId) {
      listEnv_spectrum({
        envSpmountedectrumId: this.baseInfo.envSpectrumId,
      }).then((response) => {
        this.envSpectrum = response.rows[0];
        console.log("查看环境光谱", this.envSpectrum);
      });
    } else {
      this.envSpectrum = {};
      // return;
    }

    listConstructDetail({
      constructId: this.baseInfo.constructId,
    }).then((res) => {
      this.tableData = res.rows;
      this.total = res.total;
      console.log("查看明细", this.tableData);
      
      // 自动选中第一页的全部数据
      this.$nextTick(() => {
        if (this.tableData && this.tableData.length > 0) {
          // 选中当前页的所有数据
          this.tableData.forEach(row => {
            this.$refs.dataTable.toggleRowSelection(row, true);
          });
        }
      });
    });
    // 获取环境光谱信息
    console.log("获取建模明细", this.tableData);
    console.log("查看baseInfo", this.baseInfo);
  },
  methods: {
    deleteDetailById(id) {
      if (!id) {
        this.$message.warning("无效的记录 ID，无法删除");
        return;
      }

      let message =
        this.baseInfo.constructStateName === "暂存"
          ? "确定要删除这条数据吗？"
          : "删除任意明细都会清空异常剔除结果，建模数据状态将回退为【暂存】，确定要删除这条数据吗？";

      this.$confirm(message, "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          return delConstructDetail(id);
        })
        .then((res) => {
          if (res.code === 200) {
            this.$message.success("删除成功");
            if (this.baseInfo.constructStateName !== "暂存") {
              // 如果状态不是暂存，则更新状态回退为暂存
              return updateConstruct({
                constructId: this.baseInfo.constructId,
                constructStateCode: "01",
                constructStateName: "暂存",
              }).then(() => {
                this.getList();
              });
            } else {
              this.getList();
            }
          } else {
            this.$message.error(res.msg || "删除失败");
          }
        })
        .catch((err) => {
          if (err !== "cancel") {
            this.$message.error("删除异常");
            console.error("删除失败：", err);
          }
        });
    },

    deleteEnvSpectrum() {
      this.$confirm(
        "删除环境光谱将使建模数据状态设置为“暂存”,是否删除？",
        "提示",
        {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        }
      )
        .then(() => {
          updateConstruct({
            constructId: this.baseInfo.constructId,
            envSpectrumId: "00",
            envSpectrumNo: "00",
            constructStateName: "暂存",
            constructStateCode: "01",
          }).then((res) => {
            this.$modal.msgSuccess(res.msg);
            if (res.code === 200) {
              this.$message.success("删除成功");
              this.envSpectrum = {};
            }
          });
          getConstruct(this.baseInfo.constructId).then((res) => {
            Object.keys(res.data).forEach((key) => {
              this.$set(this.baseInfo, key, res.data[key]);
            });
          });
        })
        .catch(() => {
          this.$message.info("已取消删除");
        });
    },
    async handleIssue() {
      if (this.baseInfo.constructStateName === "已完成") {
        this.$message.warning("建模已完成，无法提交");
        return;
      }
      try {
        // 1. 如果有临时的异常剔除结果，先保存到数据库
        if (this.tempPartitionResults.size > 0) {
          // 获取全部明细数据（不仅仅是当前页）
          const allDataRes = await listConstructDetail({
            constructId: this.baseInfo.constructId,
            isDelete: 0,
            pageNum: 1,
            pageSize: 999999,
          });
          const allTableData = allDataRes.rows;
          
          // 准备提交的数据：包含异常剔除结果的完整数据
          const dataToSubmit = allTableData.map(item => {
            if (this.tempPartitionResults.has(item.constructDetailId)) {
              const tempResult = this.tempPartitionResults.get(item.constructDetailId);
              return {
                ...item,
                constructdStateName: tempResult.constructdStateName,
                constructdStateCode: tempResult.constructdStateCode,
                constructdTypeName: tempResult.constructdTypeName,
                constructdTypeCode: tempResult.constructdTypeCode
              };
            }
            return item;
          });
          
          // 提交异常剔除结果到数据库
          const detailRes = await submitAbnormalPartitionResult(dataToSubmit);
          if (detailRes.code !== 200) {
            this.$message.error("建模明细提交失败");
            return;
          }
          
          // 清空临时存储
          this.tempPartitionResults.clear();
          this.$modal.msgSuccess("异常剔除结果已保存");
        } else {
          // 没有临时结果，获取全部数据并直接提交
          const allDataRes = await listConstructDetail({
            constructId: this.baseInfo.constructId,
            isDelete: 0,
            pageNum: 1,
            pageSize: 999999,
          });
          const detailRes = await submitAbnormalPartitionResult(allDataRes.rows);
          if (detailRes.code !== 200) {
            this.$message.error("建模明细提交失败");
            return;
          }
        }

        // 2. 提交建模主表状态
        const payload = {
          constructId: this.baseInfo.constructId,
          testSize: parseFloat(this.selectForm.cvRatio), // 转换为数字类型
          abnormalEliminationCode:
            this.selectForm.outlierMethod === "no_detect" ? "01" : "02",
          abnormalEliminationName: this.selectForm.outlierMethod,
          dataPartitioningCode:
            this.selectForm.splitMethod === "spxy" ? "02" : "01",
          dataPartitioningName: this.selectForm.splitMethod,
          sampleCategoryArray: JSON.stringify(this.category),
          pc1Array: JSON.stringify(this.pc1),
          pc2Array: JSON.stringify(this.pc2),
        };

        // 如果 envSpectrum 有值（不是 null 或 undefined），则添加构建状态字段
        if (this.envSpectrum && Object.keys(this.envSpectrum).length > 0) {
          payload.constructStateName = "已完成";
          payload.constructStateCode = "02";
        }

        const constructRes = await updateConstruct(payload);
        console.log(JSON.stringify(this.category));

        if (constructRes.code === 200) {
          this.$modal.msgSuccess("提交成功");
          getConstruct(this.baseInfo.constructId).then((res) => {
            Object.assign(this.baseInfo, res.data);
          });
          // 刷新列表以获取最新的数据库状态
          this.getList();
        } else {
          this.$message.error("建模数据提交失败");
        }
      } catch (error) {
        console.error("提交异常：", error);
        this.$message.error("提交失败，请稍后重试");
      }
    },

    getList() {
      listConstructDetail({
        constructId: this.baseInfo.constructId,
        pageNum: this.queryParams.pageNum,
        pageSize: this.queryParams.pageSize,
      }).then((res) => {
        this.tableData = res.rows;
        
        // 应用临时存储的异常剔除结果
        this.tableData.forEach(item => {
          if (this.tempPartitionResults.has(item.constructDetailId)) {
            const tempResult = this.tempPartitionResults.get(item.constructDetailId);
            item.constructdStateName = tempResult.constructdStateName;
            item.constructdStateCode = tempResult.constructdStateCode;
            item.constructdTypeName = tempResult.constructdTypeName;
            item.constructdTypeCode = tempResult.constructdTypeCode;
          }
        });
        
        this.total = res.total; // 假设接口返回总条数字段为 total
        // console.log("查看明细", this.tableData);
        
        // 自动选中当前页的全部数据
        this.$nextTick(() => {
          if (this.tableData && this.tableData.length > 0) {
            // 先清空之前的选择
            this.$refs.dataTable.clearSelection();
            // 选中当前页的所有数据
            this.tableData.forEach(row => {
              this.$refs.dataTable.toggleRowSelection(row, true);
            });
          }
        });
      });
    },
    handlePageChange(page) {
      this.queryParams.pageNum = page;
      this.getList(); // 重新请求数据
    },

    async handleAbnormalPartition() {
      if (!this.selectForm.outlierMethod) {
        this.$message.error("请选择异常剔除方法");
        return;
      }
      if (!this.selectForm.splitMethod) {
        this.$message.error("请选择数据划分方法");
        return;
      }
      if (this.selectForm.cvRatio === "") {
        this.$message.error("请输入验证集占比");
        return;
      }

      // 检查环境光谱数据
      if (!this.envSpectrum || !this.envSpectrum.wavelength) {
        this.$message.error(
          "未找到环境光谱数据，请先添加环境光谱后再进行异常剔除处理。"
        );
        return;
      }

      try {
        // Step 1: 拉取明细数据
        // TODO 考虑游标，分页查询，写到后端，方便复用
        const res = await listConstructDetail({
          constructId: this.baseInfo.constructId,
          isDelete: 0,
          pageNum: 1,
          pageSize: 999999,
        });
        this.tableData = res.rows;
        console.log("查看明细----", this.tableData);

        // 校验数据数量
        if (this.tableData.length < 20) {
          this.$message.error("明细数据少于20条，无法建模");
          return;
        }

        // Step 2: 构造 wave_data
        const wave_data = this.tableData.map((row) => {
          const waveList = row.wavelength.split(",").map((val) => {
            const num = parseFloat(val.trim());
            return isNaN(num) ? 0 : Number(num.toFixed(7));
          });

          const standardNum = parseFloat(row.standard);
          waveList.unshift(
            isNaN(standardNum) ? 0 : Number(standardNum.toFixed(4))
          );
          return waveList;
        });

        const env_wave_data = this.envSpectrum?.wavelength
          ? this.envSpectrum.wavelength.split(",").map((val) => {
              const num = parseFloat(val.trim());
              return isNaN(num) ? 0 : Number(num.toFixed(7));
            })
          : this.generateDefaultEnvData();

        console.log("处理的波长数据:", wave_data);
        console.log("环境光谱数据:", env_wave_data);

        // Step 3: 构造请求体并请求后端
        const payload = {
          abnormal_methord: this.selectForm.outlierMethod,
          partitioning_mathord: this.selectForm.splitMethod,
          env_wave_data: env_wave_data,
          wave_data: wave_data,
          in_spectrum: true,
          test_size: parseFloat(this.selectForm.cvRatio),
        };

        console.log("请求体:", payload);

        const response = await axios.post(
          "/api-abnormal/consruct-data/abnormal-partition",
          payload
        );
        const d_split = response.data.result.data_split;
        const o_detection = response.data.result.outlier_detection;

        // 初始化图表数据
        this.category = [];
        this.pc1 = [];
        this.pc2 = [];

        // Step 4: 设置异常样本
        o_detection.outliers_idx.forEach((idx, i) => {
          this.category[idx] = 0;
          this.pc1[idx] = Number(o_detection.outliers_pc1[i].toFixed(4));
          this.pc2[idx] = Number(o_detection.outliers_pc2[i].toFixed(4));
        });

        // Step 5: 设置训练集
        d_split.train_idx.forEach((idx, i) => {
          const idx1 = o_detection.cleaned_idx[idx];
          this.category[idx1] = 1;
          this.pc1[idx1] = Number(d_split.train_pc1[i].toFixed(4));
          this.pc2[idx1] = Number(d_split.train_pc2[i].toFixed(4));
        });

        // Step 6: 设置验证集
        d_split.test_idx.forEach((idx, i) => {
          const idx1 = o_detection.cleaned_idx[idx];
          this.category[idx1] = 2;
          this.pc1[idx1] = Number(d_split.text_pc1[i].toFixed(4));
          this.pc2[idx1] = Number(d_split.text_pc2[i].toFixed(4));
        });

        console.log("kk:", this.category);
        console.log("pc1:", this.pc1);
        console.log("pc2:", this.pc2);

        // Step 7: 更新表格显示内容并保存到临时存储
        this.tableData.forEach((row, idx) => {
          const cat = this.category[idx];
          let tempResult = {};
          
          if (cat === 0) {
            row.constructdStateName = "剔除";
            row.constructdStateCode = "02";
            tempResult = {
              constructdStateName: "剔除",
              constructdStateCode: "02",
              constructdTypeName: row.constructdTypeName, // 保持原有数据划分
              constructdTypeCode: row.constructdTypeCode
            };
          } else if (cat === 1) {
            row.constructdStateName = "正常";
            row.constructdStateCode = "01";
            row.constructdTypeName = "校正集";
            row.constructdTypeCode = "01";
            tempResult = {
              constructdStateName: "正常",
              constructdStateCode: "01",
              constructdTypeName: "校正集",
              constructdTypeCode: "01"
            };
          } else if (cat === 2) {
            row.constructdStateName = "正常";
            row.constructdStateCode = "01";
            row.constructdTypeName = "验证集";
            row.constructdTypeCode = "02";
            tempResult = {
              constructdStateName: "正常",
              constructdStateCode: "01",
              constructdTypeName: "验证集",
              constructdTypeCode: "02"
            };
          }
          
          // 保存到临时存储，不立即写入数据库
          this.tempPartitionResults.set(row.constructDetailId, tempResult);
        });

        console.log("更新后的明细数据:", this.tableData);
        
        // ✅ 所有数据准备完之后再切换 tab
        this.activeTab = "info";
        
        // 显示处理成功的消息
        this.$modal.msgSuccess("异常剔除处理完成！结果已更新，请点击提交按钮保存到数据库。");
      } catch (error) {
        if (error.response) {
          console.error("后端500错误:", error.response.data);
        } else {
          console.error("请求失败:", error);
        }
      }
    },

    handleCvRatioChange(val) {
      if (val <= 0 || val >= 1) {
        this.$message.error("请输入 0 到 1 之间的数值");
        this.selectForm.cvRatio = "";
      }
    },
    // 生成默认环境光谱数据（与明细数据波长范围一致）
    generateDefaultEnvData() {
      if (!this.tableData || this.tableData.length === 0) {
        return [];
      }
      
      // 获取第一个明细数据的波长范围
      const firstRow = this.tableData[0];
      const wavelengthCount = firstRow.wavelength.split(",").length;
      
      // 生成与明细数据相同长度的默认环境光谱（小值避免零除）
      const defaultEnvData = Array(wavelengthCount).fill(0.001);
      
      console.log(`生成默认环境光谱数据，长度: ${wavelengthCount}`);
      return defaultEnvData;
    },
    resetDetail() {
      // 清空异常剔除和数据划分状态，删除建模数据的异常剔除方法、test_size等信息
      this.$confirm("是否重置建模明细？", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          resetConstructDetail(this.baseInfo.constructId).then((res) => {
            this.$message.success(res.msg);
          });
          this.getList();
          getConstruct(this.baseInfo.constructId).then((res) => {
            this.baseInfo = res.data;
          });
          this.pc1 = [];
          this.pc2 = [];
          this.category = [];
        })
        .catch(() => {
          this.$message.info("已取消重置");
        });
    },
    deleteDetail() {
      this.$confirm("是否删除明细？", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          delConstructDetailByConstrudtId(this.baseInfo.constructId).then(
            (res) => {
              this.$message.success(res.msg);
              this.tableData = [];
            }
          );
        })
        .catch(() => {
          this.$message.info("已取消删除");
        });
      this.getList(); // 刷新列表
    },
    handleSelectionChange(selection) {
      this.selectedRows = selection;

      const newSeries = [];
      let xAxisSet = new Set();

      for (const row of selection) {
        const start = Number(row.startWavelength);
        const end = Number(row.endWavelength);
        const waveStr = row.wavelength;
        const waveArr = waveStr.split(",").map(Number);

        const x = Array.from({ length: end - start }, (_, i) =>
          (start + i).toString()
        );
        x.forEach((w) => xAxisSet.add(w));

        newSeries.push({
          name: row.constructDetailNo,
          type: "line",
          data: waveArr,
        });
      }

      this.series = newSeries;
      this.xAxis = Array.from(xAxisSet).sort((a, b) => a - b);
    },
    handleCancelUpload() {
      this.uploadDeatil_dialogVisible = false;
      this.fileContent = null; // 清空文件内容
      this.$refs.upload.clearFiles();
    },
    handleCSVUpload(file) {
      this.fileContent = file;
    },
    async saveDetail() {
      if (!this.fileContent) {
        this.$message.error("请先上传文件");
        return;
      }

      const loadingInstance = this.$loading({
        lock: true,
        text: "正在上传并插入数据，请稍候...",
        spinner: "el-icon-loading",
        background: "rgba(0, 0, 0, 0.4)",
      });

      const file = this.fileContent;
      const reader = new FileReader();

      reader.onload = async (e) => {
        try {
          const content = e.target.result;
          const lines = content.trim().split("\n");

          const header = lines[0].split(",");

          console.log("文件头部信息", header);
          console.log("文件内容", content);
          console.log("文件行数", lines);
          // 自动识别波长列的开始和结束索引
          const wavelengthIndexes = header
            .map((col, index) => {
              const num = parseInt(col);
              return isNaN(num) ? null : { index, value: num };
            })
            .filter((item) => item !== null);

          if (wavelengthIndexes.length === 0) {
            this.$message.error("未在表头中识别到波长列");
            loadingInstance.close();
            return;
          }

          const startIndex = wavelengthIndexes[0].index;
          const endIndex =
            wavelengthIndexes[wavelengthIndexes.length - 1].index;
          const startWavelength = wavelengthIndexes[0].value;
          const endWavelength =
            wavelengthIndexes[wavelengthIndexes.length - 1].value;

          // 波长范围一致性校验
          if (this.tableData && this.tableData.length > 0) {
            const existingStartWavelength = this.tableData[0].startWavelength;
            const existingEndWavelength = this.tableData[0].endWavelength;
            
            if (startWavelength !== existingStartWavelength || endWavelength !== existingEndWavelength) {
              this.$message.error(
                `波长范围不一致！当前建模数据的波长范围是 ${existingStartWavelength}-${existingEndWavelength}，` +
                `但上传文件的波长范围是 ${startWavelength}-${endWavelength}。请确保所有明细数据使用相同的波长范围。`
              );
              loadingInstance.close();
              return;
            }
          }

          const dataRows = lines.slice(1);
          console.log("数据行", dataRows);

          // 批量处理所有数据行
          const insertPromises = [];
          let successCount = 0;
          let errorCount = 0;

          for (let row of dataRows) {
            const values = row.split(",");

            if (values.length < endIndex + 2) {
              console.warn("跳过格式不对的行：", row);
              errorCount++;
              continue;
            }

            const wavelengthValues = values.slice(startIndex, endIndex + 1);
            const standard = parseFloat(
              Number(values[endIndex + 1]).toFixed(4)
            );
            console.log("标准值", standard);

            const detail = {
              constructId: this.baseInfo.constructId,
              constructNo: this.baseInfo.constructNo,
              standard: parseFloat(standard),
              startWavelength: startWavelength,
              endWavelength: endWavelength,
              wavelength: wavelengthValues.join(","),
            };

            // 收集所有插入操作的Promise，而不是逐个await
            insertPromises.push(
              addConstructDetail(detail)
                .then(() => {
                  successCount++;
                })
                .catch((err) => {
                  console.error("插入失败：", detail, err);
                  errorCount++;
                })
            );
          }

          // 并行执行所有插入操作
          await Promise.all(insertPromises);

          // 只在最后刷新一次列表
          this.getList();

          if (errorCount > 0) {
            this.$message.warning(`成功插入${successCount}条数据，${errorCount}条数据插入失败`);
          } else {
            this.$message.success(`成功插入${successCount}条数据`);
          }
          
          this.uploadDeatil_dialogVisible = false;
        } catch (error) {
          console.error("处理文件异常：", error);
          this.$message.error("上传过程中出错");
        } finally {
          loadingInstance.close(); // 无论成功失败都关闭 loading
          this.fileContent = null; // 清空文件内容
        }
      };

      reader.readAsText(file.raw, "utf-8");
    },

    handleDownload() {
      let start = 200;
      let end = 1099;
      
      // 如果已经有明细数据，使用已有数据的波长范围
      if (this.tableData && this.tableData.length > 0) {
        start = this.tableData[0].startWavelength;
        end = this.tableData[0].endWavelength;
        console.log(`使用已有数据的波长范围: ${start}-${end}`);
      } else {
        console.log(`使用默认波长范围: ${start}-${end}`);
      }
      
      const wavelengthCount = end - start + 1;

      const header = [];
      for (let i = start; i <= end; i++) {
        header.push(i);
      }
      header.push("标准值");

      const rows = [];
      const sampleCount = 20; // 示例生成10个样本
      for (let i = 0; i < sampleCount; i++) {
        const row = [];
        for (let j = 0; j < wavelengthCount; j++) {
          // 模拟吸光度：0.05 - 1.0 之间的随机值
          row.push((Math.random() * 0.95 + 0.05).toFixed(4));
        }
        // 模拟西瓜糖度（标准值）：7.0 - 12.0
        row.push((Math.random() * 5 + 7).toFixed(2));
        rows.push(row);
      }

      const csvContent = [header, ...rows].map((e) => e.join(",")).join("\n");
      const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
      const link = document.createElement("a");
      const url = URL.createObjectURL(blob);
      link.setAttribute("href", url);
      
      // 根据是否有已有数据生成不同的文件名
      const fileName = this.tableData && this.tableData.length > 0 
        ? `匹配现有数据的光谱模板_${start}-${end}.csv`
        : `示例光谱数据.csv`;
      
      link.setAttribute("download", fileName);
      link.click();
      URL.revokeObjectURL(url);
      this.$modal.msgSuccess("下载成功");
    },
    handleAddDetail() {
      this.uploadDeatil_dialogVisible = true;
      this.$emit("addDetail");
    },
    handleRowSelection(selection) {
      const tableRef = this.$refs.envSpectrumDetail.$refs.envTable;
      if (selection.length > 1) {
        const lastSelected = selection[selection.length - 1];
        this.$nextTick(() => {
          tableRef.clearSelection(); // 清除所有选中
          tableRef.toggleRowSelection(lastSelected, true); // 仅保留当前选中
        });
        this.selectedEnvSpectrum = lastSelected;
      } else {
        this.selectedEnvSpectrum = selection[0] || null;
      }
      console.log("查看选中的环境光谱", this.selectedEnvSpectrum);
    },
    submitForm() {
      if (this.selectedEnvSpectrum == null) {
        this.$modal.msgError("请选择要关联的环境光谱");
        return;
      }
      const payload = {
        constructId: this.baseInfo.constructId,
        envSpectrumId: this.selectedEnvSpectrum.envSpectrumId,
        envSpectrumNo: this.selectedEnvSpectrum.envSpectrumNo,
      };

      // 判断是否有 pc1Array，再决定是否设置状态字段
      if (this.baseInfo.pc1Array && this.baseInfo.pc1Array.length > 0) {
        payload.constructStateName = "已完成";
        payload.constructStateCode = "02";
      }
      updateConstruct(payload).then((res) => {
        this.$modal.msgSuccess(res.msg);
        if (res.code === 200) {
          this.$emit("ok");
        }
      });
      this.envdialogVisible = false;
      listEnv_spectrum({
        envSpectrumId: this.selectedEnvSpectrum.envSpectrumId,
      }).then((response) => {
        this.envSpectrum = response.rows[0];
      });
    },
    cancel() {
      this.envdialogVisible = false;
      // this.reset();
    },
    handleAddEnvSpectrum() {
      // 弹出对话框
      this.envdialogVisible = true;
    },
    dataTypeTag(type) {
      switch (type) {
        case "校正集":
          return "primary";
        case "验证集":
          return "warning";
        default:
          return "";
      }
    },
  },
};
</script>

<style>
html,
body,
#app {
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden !important;
}
</style>
<style scoped>
.app-container {
  height: 95vh; /* 或者固定高度，例如 800px */
  overflow: auto; /* ✅ 正确写法：CSS里写，而不是HTML里写 */
  padding: 10px;
  box-sizing: border-box;
}

.base-box-card {
  min-height: 80px; /* 设置最小高度 */
  max-height: 150px; /* 设置最大高度，避免占用过多空间 */
  height: auto; /* 自适应内容高度 */
  overflow-y: auto; /* 如果内容超过最大高度，显示滚动条 */
  margin-right: 0.1%;
  background-color: #f5f5f5; /* 接近白色的浅灰 */
  border: #e0e0e0 1px solid; /* 边框颜色与背景色相同 */
  margin-top: 5px;
  font-size: 14px;
  /* padding: 15px; 增加内边距，让内容更好显示 */
}

.main-row {
  margin-top: 5px;
  display: flex;
}

.left-size {
  padding-right: 10px;
  width: 70%;
  height: 98%;
}

.right-size {
  width: 30%;
  height: 100%;
}

.box-card {
  margin-top: 5px;
  /* height: 80%; */
  /* height: 500px; */
}

.env-box-card {
  /* margin-top: 5px; */
  font-size: 14px;
}
.card-header {
  font-weight: bold;
  font-size: 16px;
}

.drawer-footer {
  /* width: 100%; */
  position: absolute;
  right: 2px;
  bottom: 2px;
}

.env-dialog-body {
  flex: 1;
  max-height: 60vh; /* 控制 detail 部分占多高 */
  overflow-y: auto;
  padding-right: 10px;
}
</style>
